#ifndef OPERACION_H
#define OPERACION_H

#include "ArbolBMas.h"
#include "HashExtensible.h"
#include <fstream>
#include "../Comun/MetadataClase.h"
#include "../Comun/Clase.h"
#include "../Comun/ConversorDeStreams.h"
#include "../Comun/Condiciones.h"
#include "HidratadorMetadataClase.h"
#include <list>
#include <iostream>
#include <sstream>
#include "Secuencial.h"
#include "../Comun/Sort.h"

using namespace std;
using namespace CapaIndices;



namespace CapaIndices
{
	class Operacion{
		protected:
			MetadataClase* _MetadataClase;
			list<Registro>* Resultado;
			int _CantRegistrosAfectados;
		public:
			Operacion (MetadataClase* MC);
			Operacion ();
	
			virtual void Ejecutar()=0;
	
			virtual ~Operacion();
		
			virtual bool esSeleccion();

			virtual bool esDeMetadata();

			virtual bool esInsercion();

			virtual bool esAltaClase();

			int getCantRegAfectados();
	
			list<Registro>* getResultado();

			int numero;
	
		protected:
			MetadataClase& getMetadataClase();
	
			void InsertarAtributos(MetadatosIndice& MI,InfoIndice* IIndex);
	
			IIndice* getIndice(InfoIndice* InfoIndex);

			IIndice* getIndicePorDefecto();
	
			list<IIndice*>* getIndices();

			bool TengoInfoIndicePrimario(IIndice* primario,CondicionCompuesta* CC);
	
			void agregarClavePrimaria(list<MetadatosAtributo>* Claves);
	
			void agregarClaveSecundariaActual(list<MetadatosAtributo>* Claves,InfoIndice* InfIndex);
	
			string getNombreArch(InfoIndice* InfoIndex);
	
			string getStrIndexs(InfoIndice* InfoIndex);
	
			list<string>* obtenerCamposIgual(CondicionCompuesta* CC);
	
			list<string>* obtenerCampos(CondicionCompuesta* CC);
	
			bool hayIndiceExclusivoPorCampo(string str);
	
			bool hayIndiceCompuestoPorCampo(string str,CondicionCompuesta* CC);
	
			bool esClaveUnica(string clave,list<string>& Campos);
	
			bool esPrimerClaveDe(string clave,list<string>& Campos,list<Condicion*> Condiciones);
	
			InfoIndice* getInfoIndiceDesdeNombre(string str);
	
			InfoIndice* getInfoIndicePrimerNombreClave(string str,CondicionCompuesta* CC);
	
			bool CondCompEsAND(CondicionCompuesta* CC);
	
			string IntToString(int i);
	
			string UIntToString(unsigned int i);
	
	};
	
	class OperacionSeleccion: public Operacion{
		private:
			CondicionCompuesta* _CondicionCompuesta;
			list<string>* _ColSeleccion;
	
		public:
			OperacionSeleccion(MetadataClase* MC,CondicionCompuesta* CC,list<string>* ColSel);
	
			virtual void Ejecutar();
	
			virtual ~OperacionSeleccion();

			virtual bool esSeleccion();
	
		private:
	
			list<Registro>* SeleccionarColumnas(list<Registro>* Tabla);
	
			Registro FiltrarColumnas(Registro& RegIn);
	
			bool mostrarColumna(string NombreCol);
	
			bool tieneCondFuerteConIndice(CondicionCompuesta* CC);
	
			list<Registro>* ProcesarAND();
	
			list<Registro>* ProcesarANDCampos(list<string>* Campos);
	
			list<Registro>* ProcesarOR();
	
			void EliminarRegistrosRepetidos(list<Registro>* Result, int nroOr, Atributo orden, string nombreArchivo);
	
			void ProcesarCondicionIndice(IIndice* Index,Condicion* Cnd,list<Registro>* Result, int nro);
	
	
	};
	
	class OperacionInsercion: public Operacion{
		private:
			list<ClaveValor>* _Datos;
		public:
			OperacionInsercion(MetadataClase* MC,list<ClaveValor>* Datos);
	
			virtual void Ejecutar();

			virtual bool esInsercion();
	
			virtual ~OperacionInsercion();
	};

	class OperacionExisteClase: public Operacion{
		private:
			std::string NombreClase;

		public:
			OperacionExisteClase(std::string Clase);
	
			virtual void Ejecutar();

			virtual bool esDeMetadata();
	
			virtual ~OperacionExisteClase();
	};

	class OperacionGetMetadataClase: public Operacion{
		private:
			std::string NombreClase;

		public:
			OperacionGetMetadataClase(std::string Clase);
	
			virtual void Ejecutar();

			virtual bool esDeMetadata();

			virtual ~OperacionGetMetadataClase();
	};
	
	class OperacionActualizacion: public Operacion{
		private:
			list<ClaveValor>* _Datos;
			CondicionCompuesta* _CondicionCompuesta;
		public:
			OperacionActualizacion(MetadataClase* MC,list<ClaveValor>* Datos,CondicionCompuesta* CC);			
	
			virtual void Ejecutar();

			void EjecutarPrimario(CondicionCompuesta* CC);

			void EjecutarSecundario(IIndice* Indice,CondicionCompuesta* CC);
	
			virtual ~OperacionActualizacion();
	};
	
	class OperacionBorrado: public Operacion{
		private:
			CondicionCompuesta* _CondicionCompuesta;
		public:
			OperacionBorrado(MetadataClase* MC,CondicionCompuesta* CC);
	
			virtual void Ejecutar();

			void EjecutarPrimario(CondicionCompuesta* CC, bool llamadaRoot);

			void EjecutarSecundario(IIndice* Indice,CondicionCompuesta* CC, bool llamadaRoot);
	
			virtual ~OperacionBorrado();
	};
	
	class OperacionAltaClase: public Operacion{
		private:
	
		public:
			OperacionAltaClase(MetadataClase* MC);
	
			virtual void Ejecutar();

			virtual bool esAltaClase();
	
			void CrearIndice(InfoIndice* InfoIndex);
	
	
			virtual ~OperacionAltaClase();
	};

}

#endif
